package com.smartstate.EnvironmentMonitor.schedul;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson.JSON;
import com.smartstate.EnvironmentMonitor.config.BeanContext;
import com.smartstate.EnvironmentMonitor.entity.EquipmentConfiguration;
import com.smartstate.EnvironmentMonitor.entity.Report;
import com.smartstate.EnvironmentMonitor.mapper.DataMapper;
import com.smartstate.EnvironmentMonitor.mapper.HistoryMapper;
import com.smartstate.EnvironmentMonitor.service.HistoryService;
import com.smartstate.EnvironmentMonitor.vo.DataVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;

@Slf4j
public class DataRealThread implements Callable<Map<String, List<DataVO>>> {

    private HistoryService historyService;

    private HistoryMapper historyMapper;

    public RedisTemplate redisTemplate;

    public DataMapper dataMapper;

    public SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private String userId;

    private DataVO dataVO;

    private String check;

    public DataRealThread(String userId, DataVO dataVO, String check){
        historyMapper = BeanContext.getApplicationContext().getBean(HistoryMapper.class);
        redisTemplate = (RedisTemplate) BeanContext.getApplicationContext().getBean("redisTemplate");
        dataMapper = BeanContext.getApplicationContext().getBean(DataMapper.class);
        historyService = BeanContext.getApplicationContext().getBean(HistoryService.class);
        this.userId = userId;
        this.dataVO = dataVO;
        this.check = check;
    }

    @Override
    public Map<String, List<DataVO>> call() {
        Map<String, List<DataVO>> mapAttribute = new HashMap<>();
        String attributeValue = (String) redisTemplate.opsForHash().get(dataVO.getId(), dataVO.getAttribute());
        attributeValue = attributeValue == null ? "0.0" : attributeValue;
        attributeValue = attributeValue.replace("\"", "");
        BigDecimal bigDecimal = new BigDecimal(attributeValue);
        String compensationValue = queryCompensationValue(dataVO.getId(), dataVO.getAttribute());
        attributeValue = bigDecimal.add(new BigDecimal(compensationValue)).toString();
        dataVO.setCurrentValue(attributeValue);
        dataVO.setTime(simpleDateFormat.format(new Date()));
//                    获取每个属性的前59条历史数据+1条实时数据
        List<DataVO> historyCollect = null;
//                   获取environmentalmonitoring超级表中的所有子表，判断下面要查询的表是否存在
        if (!"".equals(check)){
//              判断要查询的表是否存在
            String id = dataMapper.queryIdByDeviceId(dataVO.getId());
            String tableIsEmpty = historyMapper.queryTableIsEmpty(id);
            if (tableIsEmpty != null){
                List<Report> historyCurveByDeviceId = historyService.getHistoryCurveByDeviceId(id);
//                            判断查询时间内的历史数据为空
                if(historyCurveByDeviceId.size() > 0){
                    Collections.reverse(historyCurveByDeviceId);
                }else {
                    log.info("TD中查不到该设备的近期3分钟内历史时间");
                }
                historyCollect = historyCurveByDeviceId.stream().map((report) -> {
                    DataVO dataVO1 = null;
                    Object historyValue = invokeGet(report, dataVO.getAttribute());
                    if (historyValue != null){
                        dataVO1 = new DataVO();
                        dataVO1.setId(dataVO.getId());
                        dataVO1.setAttribute(dataVO.getAttribute());
                        dataVO1.setCurrentValue(historyValue.toString());
                        dataVO1.setTime(simpleDateFormat.format(report.getDateTime()));
                    }
                    return dataVO1;
                }).collect(Collectors.toList());
//                            判断redis中是否有数据，如果没有就不需要构建空数据
            }else if(dataVO.getCurrentValue() != null){
//                            表不存在的情况,构造59条空数据
                historyCollect = new ArrayList<>();
                int count2 = 0;
                while(count2 < 59){
                    DataVO dataVO = new DataVO();
                    dataVO.setId(dataVO.getId());
                    dataVO.setAttribute(dataVO.getAttribute());
                    dataVO.setCurrentValue("0.0");
                    dataVO.setTime(new DateTime().offsetNew(DateField.SECOND, -(count2+1)).toString());
                    historyCollect.add(dataVO);
                    count2 ++;
                }
            }
        }else {
            historyCollect = new ArrayList<>();
        }
        if(historyCollect != null)
            historyCollect.removeAll(Collections.singleton(null));
        if(dataVO.getCurrentValue() != null){
            historyCollect.add(dataVO);
        }
        mapAttribute.put(dataVO.getId() + "." + dataVO.getAttribute(),historyCollect);
        return mapAttribute;
    }

    /**
     * java反射bean的get方法
     *
     * @param
     * @param fieldName
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Method getGetMethod(Report objectClass, String fieldName) {
        StringBuffer sb = new StringBuffer();
        sb.append("get");
        sb.append(fieldName.substring(0, 1).toUpperCase());
        sb.append(fieldName.substring(1));
        try {
            return objectClass.getClass().getMethod(sb.toString());
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * 执行get方法
     *
     * @param o 执行对象
     * @param fieldName 属性
     */
    public static Object invokeGet(Report o, String fieldName) {
        Method method = getGetMethod(o, fieldName);
        try {
            return method.invoke(o, new Object[0]);
        } catch (Exception e) {
            log.info("输入格式有误，数据读不出");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取设备对应的补偿值
     * @param deviceId
     * @return
     */
    public String queryCompensationValue(String deviceId, String attribute){
        EquipmentConfiguration equipmentConfiguration = dataMapper.queryCompensationValue(deviceId);
        if (equipmentConfiguration == null || equipmentConfiguration.getTags() == null){
            return "0.0";
        }
        List<Map> lists = JSON.parseArray(equipmentConfiguration.getTags(), Map.class);
        List<Object> collect = lists.stream().filter(item -> item.containsKey("attributeName") && item.containsKey("deviation"))
                .filter(item -> item.get("attributeName").equals(attribute)).map(s -> s.get("deviation")).collect(Collectors.toList());
        return collect.size() > 0 ? collect.get(0).toString() : "0.0";
    }
}
